import type {
  MemberResponse,
  ProjectMemberRoleResponse,
  UpdateProjectRolesArgs,
  TeamResponse,
  TeamMemberResponse,
} from "generatedApi";
import { useRouter } from "next/router";
import { useRef, useState } from "react";
import { Button } from "@ui/Button";
import { Tooltip } from "@ui/Tooltip";
import { Combobox, Option } from "@ui/Combobox";
import { ConfirmationDialog } from "@ui/ConfirmationDialog";
import { CaretSortIcon } from "@radix-ui/react-icons";
import { useMount } from "react-use";
import classNames from "classnames";
import startCase from "lodash/startCase";
import Link from "next/link";
import { Callout } from "@ui/Callout";
import { MemberProjectRolesModal } from "./MemberProjectRolesModal";

export const roleOptions: Option<"admin" | "developer">[] = [
  { label: "Admin", value: "admin" },
  { label: "Developer", value: "developer" },
];

type TeamMemberListItemProps = {
  team: TeamResponse;
  myProfile: MemberResponse;
  member: TeamMemberResponse;
  members: TeamMemberResponse[];
  canChangeRole: boolean;
  onChangeRole: (body: {
    memberId: number;
    role: "admin" | "developer";
  }) => Promise<Response>;
  onRemoveMember: (body: { memberId: number }) => Promise<Response>;
  onUpdateProjectRoles: (body: UpdateProjectRolesArgs) => Promise<undefined>;
  hasAdminPermissions: boolean;
  projectRoles: ProjectMemberRoleResponse[];
};
export function TeamMemberListItem({
  team,
  myProfile,
  member,
  members,
  canChangeRole,
  onChangeRole,
  onUpdateProjectRoles,
  onRemoveMember,
  hasAdminPermissions,
  projectRoles,
}: TeamMemberListItemProps) {
  const router = useRouter();
  const isMemberTheLastAdmin =
    members.filter((m) => m.role === "admin" && m.id !== member.id).length ===
    0;
  const isMemberMe = member.id === myProfile?.id;

  const canManageMember =
    (hasAdminPermissions || isMemberMe) && !isMemberTheLastAdmin;

  const isHighlighted = window.location.hash === `#${member.id}`;

  const ref = useRef<HTMLDivElement | null>(null);
  useMount(() => {
    isHighlighted && ref.current?.scrollIntoView();
  });

  let removeMemberMessage = "";
  if (isMemberTheLastAdmin) {
    removeMemberMessage =
      "You cannot remove the last admin from this team. Contact us for help at support@convex.dev";
  } else if (!canManageMember) {
    removeMemberMessage =
      "You do not have permission to remove members from this team.";
  }

  let updateRoleMessage = "";
  if (team.managedBy) {
    updateRoleMessage = `This team is managed by ${startCase(team.managedBy)}. You may manage team roles in ${startCase(team.managedBy)}.`;
  } else if (isMemberTheLastAdmin) {
    updateRoleMessage = "You cannot change the role of the last admin.";
  } else if (!hasAdminPermissions) {
    updateRoleMessage = "You do not have permission to change member roles.";
  }

  const [showRemoveMember, setShowRemoveMember] = useState(false);

  const [isUpdatingRole, setIsUpdatingRole] = useState(false);

  const confirmationDisplayName = member.name
    ? `${member.name} (${member.email})`
    : member.email;

  const [showProjecRolesModal, setShowProjectRolesModal] = useState(false);

  return (
    <div
      ref={ref}
      className={classNames(
        "flex flex-wrap justify-between items-center gap-4 py-2",
        isHighlighted
          ? "bg-highlight px-2 -mx-2 rounded-sm border"
          : "border-b last:border-b-0",
      )}
    >
      <div className="flex max-w-[40%] flex-col sm:max-w-[50%] md:max-w-[80%]">
        {member.name && (
          <div className="text-sm text-content-primary">{member.name}</div>
        )}
        <div
          className={`${
            member.name
              ? "text-xs text-content-secondary"
              : "text-sm text-content-primary"
          }`}
        >
          {member.email}
        </div>
      </div>
      <div className="flex flex-wrap items-center gap-2">
        <div className="flex items-center gap-2">
          {!canChangeRole ? (
            <div className="text-sm text-content-primary">
              {startCase(member.role)}
            </div>
          ) : !canManageMember || team.managedBy ? (
            // Combobox is difficult to create a disabled state for, so we're using a div here that looks like a disabled input
            <Tooltip tip={updateRoleMessage}>
              <div className="flex cursor-not-allowed items-center gap-1 rounded-sm border bg-background-tertiary p-1.5 text-content-secondary">
                {startCase(member.role)}
                <CaretSortIcon className="h-5 w-5" />
              </div>
            </Tooltip>
          ) : (
            <Combobox
              buttonClasses="w-fit"
              disableSearch
              label="Role"
              options={roleOptions}
              selectedOption={member.role}
              buttonProps={{
                loading: isUpdatingRole,
                tip: (
                  <span>
                    Change this member's{" "}
                    <Link
                      href="https://docs.convex.dev/dashboard/teams#roles-and-permissions"
                      className="underline"
                    >
                      team role
                    </Link>
                    .
                  </span>
                ),
                tipSide: "top",
              }}
              setSelectedOption={async (role) => {
                if (!role) {
                  return;
                }
                setIsUpdatingRole(true);
                try {
                  await onChangeRole({ memberId: member.id, role });
                } finally {
                  setIsUpdatingRole(false);
                }
              }}
            />
          )}
        </div>
        <Button
          variant="neutral"
          onClick={() => setShowProjectRolesModal(true)}
        >
          Project Roles ({projectRoles?.length || 0})
        </Button>
        <Button
          variant="danger"
          disabled={!canManageMember}
          tip={removeMemberMessage}
          onClick={() => setShowRemoveMember(true)}
        >
          {isMemberMe ? "Leave team" : "Remove member"}
        </Button>
        {showRemoveMember && (
          <ConfirmationDialog
            onClose={() => setShowRemoveMember(false)}
            onConfirm={async () => {
              await onRemoveMember({ memberId: member.id });
              if (isMemberMe) {
                await router.push("/");
              }
            }}
            dialogTitle={isMemberMe ? "Leave team" : "Remove team member"}
            dialogBody={
              isMemberMe ? (
                `You are about to leave ${team.name}, are you sure you want to continue?`
              ) : (
                <div className="flex flex-col gap-1">
                  <p>
                    You are about to remove {confirmationDisplayName} from{" "}
                    {team.name}, are you sure you want to continue?{" "}
                  </p>
                  {team.managedBy && (
                    <Callout>
                      Note that this member may be able to re-join the team
                      through the {startCase(team.managedBy)} dashboard if they
                      are still a member of your {startCase(team.managedBy)}{" "}
                      team.
                    </Callout>
                  )}
                </div>
              )
            }
            confirmText="Confirm"
          />
        )}
        {showProjecRolesModal && (
          <MemberProjectRolesModal
            member={member}
            team={team}
            projectRoles={projectRoles}
            onClose={() => setShowProjectRolesModal(false)}
            onUpdateProjectRoles={onUpdateProjectRoles}
          />
        )}
      </div>
    </div>
  );
}
